export default class Dictionary {
    #table = {}

    set(key, value) {
        if (key != null && value != null) {
            const tableKey = this.toStrFn(key)
            this.#table[tableKey] = new ValuePair(key, value)
        }
    }

    get(key) {
        const tableKey = this.toStrFn(key)
        return this.#table[tableKey]?.value
    }

    hasKey(key) {
        return this.#table[this.toStrFn(key)] != null
    }

    remove(key) {
        if (this.hasKey(key)) {
            delete this.#table[this.toStrFn(key)]
            return true
        }
        return false
    }

    keys() {
        return this.keyValues().map(valuePair => valuePair.key)
    }

    values() {
        return this.keyValues().map(valuePair => valuePair.value)
    }

    keyValues() {
        return Object.values(this.#table)
    }

    size() {
        return Object.keys(this.#table).length
    }

    isEmpty() {
        return this.size() === 0
    }

    clear() {
        this.#table = {}
    }

    forEach(callback) {
        const valuePair = this.valuePair()
        for (let i = 0; i < valuePair.length; i++) {
            callback(valuePair[i].vkey, valuePair[i].value)
        }
    }

    toStrFn(key) {
        if (key === null) {
            return 'NULL'
        } else if (key === undefined) {
            return 'UNDEFINED'
        } else if (typeof key === 'string' || key instanceof String) {
            return key
        }
        return JSON.stringify(key)
    }
}

class ValuePair {
    constructor(key, value) {
        this.key = key
        this.value = value
    }
}